/*******************************************************************************
 * TManager.h
 *
 * Copyright (c) 2012, Varuna L Amachi. All rights reserved.
 *
 * This program/library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This program/library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301  USA
 ******************************************************************************/

#ifndef T_H
#define T_H

#include <QDebug>
//#include <QApplication>

#include "core/components/AbstractAudioManager.h"
#include "core/components/AbstractAudioLibrary.h"
#include "core/components/AbstractPlaylist.h"
#include "core/engine/AbstractEngine.h"
#include "core/components/AbstractPlaylistManager.h"
#include "core/components/AbstractHistoryManager.h"
#include "core/datasource/IDataSourceManager.h"
#include "core/datasource/IDataRetriever.h"
#include "core/datasource/IDataUpdater.h"
#include "core/model/StoredAudio.h"

class QSqlQuery;


namespace Tanyatu
{

class TANYATU_CORE_EXPORT T
{
public:

    typedef void ( *LogWriterFunc )( QString message );

    class TANYATU_CORE_EXPORT Logger
    {
    public:
        enum LogLevel {
            Log_Debug,
            Log_Info,
            Log_Warning,
            Log_Error,
            Log_Fatal
        };

        void log( LogLevel level, QString message );

        void log( QString queryId, QSqlQuery &query );

        void setLevel( LogLevel level )
        {
            m_logLevel = level;
        }


        void debug( QString message )
        {
            log( Log_Debug, message );
        }

        void info( QString message )
        {
            log( Log_Info, message );
        }

        void warning( QString message )
        {
            log( Log_Warning, message );
        }

        void error( QString message )
        {
            log( Log_Error, message );
        }

        void fatal( QString message )
        {
            log( Log_Fatal, message );
        }


    protected:

        T::LogWriterFunc m_writerFunc;

        LogLevel m_logLevel;

        static void consoleWrite( QString message )
        {
            qDebug() << message;
        }

        Logger( LogWriterFunc func, LogLevel logLevel )
        {
            m_writerFunc = func ? func : & Logger::consoleWrite;
            m_logLevel = logLevel;
        }

        friend class T;
    };


    Engine::AbstractEngine *audioEngine()
    {
        return m_audioEngine;
    }

    Component::AbstractAudioLibrary *audioLib()
    {
        return m_audioLibrary;
    }

    Component::AbstractAudioManager *audioManager()
    {
        return m_audioManager;
    }

    Component::AbstractPlaylist *playlist()
    {
        return m_playlist;
    }

    Component::AbstractPlaylistManager *playlistManager()
    {
        return m_playlistManger;
    }

    Component::AbstractHistoryManager *historyManager()
    {
        return m_historyManager;
    }

    DataSource::IDataSourceManager *dataManager()
    {
        return m_dataManager;
    }

    virtual DataSource::IDataRetriever *dataRetriever()
    {
        return  m_dataRetriever;
    }

    virtual DataSource::IDataUpdater *dataUpdater()
    {
        return m_dataUpdater;
    }



    virtual ~T();

    static void init( Engine::AbstractEngine *audioEngine,
                     Component::AbstractAudioLibrary *audioLibrary,
                     Component::AbstractAudioManager *audioManager,
                     Component::AbstractPlaylist *playlist,
                     Component::AbstractPlaylistManager *playlistManger,
                     Component::AbstractHistoryManager *historyManager,
                     DataSource::IDataSourceManager *dataManager,
                     DataSource::IDataRetriever *dataRetriever,
                     DataSource::IDataUpdater *dataUpdater,
                     Logger::LogLevel logLevel = Logger::Log_Error,
                     LogWriterFunc logWriterFunction = 0 );

    static T *get();

    static Logger *logger();

private:

    T()
    {

    }

    Engine::AbstractEngine *m_audioEngine;

    Component::AbstractAudioLibrary *m_audioLibrary;

    Component::AbstractAudioManager *m_audioManager;

    Component::AbstractPlaylist *m_playlist;

    Component::AbstractPlaylistManager *m_playlistManger;

    Component::AbstractHistoryManager *m_historyManager;

    DataSource::IDataSourceManager *m_dataManager;

    DataSource::IDataRetriever *m_dataRetriever;

    DataSource::IDataUpdater *m_dataUpdater;

    Logger *m_logger;

    static bool s_initialized;

    static T *s_instance;
};
}


#define AUDIO_ENGINE() Tanyatu::T::get()->audioEngine()
#define AUDIO_LIB() Tanyatu::T::get()->audioLib()
#define AUDIO_MANAGER() Tanyatu::T::get()->audioManager()
#define PLAYLIST() Tanyatu::T::get()->playlist()
#define PL_MANAGER() Tanyatu::T::get()->playlistManager()
#define HISTORY_MANAGER() Tanyatu::T::get()->historyManager()
#define DATA_UPDATER() Tanyatu::T::get()->dataUpdater()
#define DATA_RETRIEVER() Tanyatu::T::get()->dataRetriever()
#define DATA_MANAGER() Tanyatu::T::get()->dataManager()


#endif // T_H
